package com.lagou.handler;

import com.lagou.RpcRequest;
import com.lagou.service.UserServiceImpl;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.concurrent.EventExecutorGroup;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 自定义的业务处理器
 */
@Component
public class UserServiceHandler extends ChannelInboundHandlerAdapter implements ApplicationContextAware {

    private static ApplicationContext context;

    //当客户端读取数据时,该方法会被调用
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {

//        //注意:  客户端将来发送请求的时候会传递一个参数:  UserService#sayHello#are you ok
//         //1.判断当前的请求是否符合规则
//        if(msg.toString().startsWith("UserService")){
//            //2.如果符合规则,调用实现类货到一个result
//            UserServiceImpl service = new UserServiceImpl();
//            String result = service.sayHello(msg.toString().substring(msg.toString().lastIndexOf("#")+1));
//            //3.把调用实现类的方法获得的结果写到客户端
//            ctx.writeAndFlush(result);
//        }

        //请求是否符合规则
        if (msg instanceof RpcRequest) {
            RpcRequest rpcRequest = (RpcRequest) msg;

            String className = rpcRequest.getClassName();
            Class<?> aClass = null;
            try {
                aClass = Class.forName(className);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }

            Object proxy = createProxy(aClass, rpcRequest);

            Method method = aClass.getDeclaredMethod(rpcRequest.getMethodName(), rpcRequest.getParameterTypes());
            Object invoke = method.invoke(proxy, rpcRequest.getParameters());

            ctx.writeAndFlush(invoke);
        }


    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("context:" + applicationContext);
        context = applicationContext;
    }

    public Object createProxy(Class<?> serviceClass, RpcRequest rpcRequest) {

        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                new Class[]{serviceClass},
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        Object bean = context.getBean(serviceClass);
                        if (bean == null) {
                            return "fail: service not found";
                        }
                        Object result = method.invoke(bean, args);
                        return result;
                    }
                });
    }
}
